package hu.szyrt.bug;

import hu.szyrt.bug.db.DBHandler;
import hu.szyrt.bug.dialogs.BUGDialog;
import hu.szyrt.bug.models.Category;
import hu.szyrt.bug.overlays.PlaceOverlayItem;
import hu.szyrt.bug.overlays.PlacesOverlay;
import hu.szyrt.bug.utils.Assets;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.nirigo.mobile.googledirectionapi.GoogleDirectionAPI;
import com.nirigo.mobile.googledirectionapi.GoogleDirectionMap;
import com.nirigo.mobile.googledirectionapi.models.Route;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MapsActivity extends MapActivity {

	private Button backButton,
		   		   locationButton,
		   		   deleteDirectionButton;
	
	public final static String KEY_PLACE_ID = "place_id";	
	private int onlyOnePlaceID = -1;
	
	private MapView mapView;
	private MapController mapController;
	private List<Overlay> overlays;

	private GeoPoint budapest = new GeoPoint(47503838,19060414);
	private int zoomLevel = 16;	
	private List<String> blockedCategories = Arrays.asList(new String[]{
			"welcome", "highlights", "deals"
	});
	
	private Assets assets;
	private DBHandler dbHandler;
	private PlacesOverlay placeOverlays;
	private MyLocationOverlay myLocationOverlay;
	private Drawable defaultDrawable;	
	
	private GeoPoint from = null, 
			 		 to = null;
	
	private GoogleDirectionAPI gda;
	private GoogleDirectionMap gdm;
	
	private GestureDetector gestureDetector;
	
	@Override
	protected void onCreate(Bundle icicle) {	
		super.onCreate(icicle);
		setContentView(R.layout.map);
		
		// Leveszük a place_id-t
		if(getIntent().getExtras() != null){
			if(getIntent().getExtras().containsKey(KEY_PLACE_ID))
				onlyOnePlaceID = getIntent().getExtras().getInt(KEY_PLACE_ID);
		}
		
		backButton = (Button)findViewById(R.id.backButton);
		backButton.setCompoundDrawables(null, null, null, null);
		backButton.setPadding(10, 0, 0, 0);
		
		locationButton = (Button)findViewById(R.id.locationButton);
		locationButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(myLocationOverlay != null)
					mapController.animateTo(myLocationOverlay.getMyLocation());
				else
					Toast.makeText(MapsActivity.this, R.string.err_map_missing_from, Toast.LENGTH_LONG).show();
			}
		});
		deleteDirectionButton = (Button) findViewById(R.id.directionDeleteButton);
		deleteDirectionButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				clearDirection();
				from = null;
				addOverlay();
			}
		});
		
		mapView = (MapView)findViewById(R.id.map);
		mapView.setBuiltInZoomControls(true);
		mapController = mapView.getController();
		mapController.setCenter(budapest);
		mapController.setZoom(zoomLevel);
		overlays = mapView.getOverlays();
				
		assets = new Assets(this);
		dbHandler = new DBHandler(this);
		
		defaultDrawable = new BitmapDrawable(getResources(), assets.loadCategoryIcon("welcome.png", 2));
				
		loadOverlays();
		
		gdm = new GoogleDirectionMap(mapView);
		
		gestureDetector = new GestureDetector(this, new MyGestureListener());
	}
	
	@Override
	protected void onResume() {
		if(myLocationOverlay != null){
			myLocationOverlay.enableMyLocation();			
		}
		super.onResume();
	}
	
	@Override
	protected void onPause() {
		if(myLocationOverlay != null){			
			myLocationOverlay.disableMyLocation();
		}
		super.onPause();
	}
	
	private void loadOverlays(){
		clearDirection();
		clearOverlays();
		
		placeOverlays = new PlacesOverlay(defaultDrawable);
		placeOverlays.setAnnotationClick(new OnClickListener() {
			public void onClick(View v) {
				int id = placeOverlays.getLastItem().getId();
				PlaceActivity.showPlaceBy(MapsActivity.this, PlaceActivity.PLACE_ID, id);				
			}
		});
		placeOverlays.setDirectionFromHereClick(new OnClickListener() {
			public void onClick(View v) {
				from = placeOverlays.getLastItem().getPoint();
				placeOverlays.hideAnnotation();
			}
		});
		placeOverlays.setDirectionToHereClick(new OnClickListener() {
			public void onClick(View v) {
				to = placeOverlays.getLastItem().getPoint();
				placeOverlays.hideAnnotation();
				startDirection();				
			}
		});
		new Thread(new Runnable() {
			public void run() {				
									
				List<Category> categories = dbHandler.loadCategories();				
				for(Category category : categories){			
					if(!blockedCategories.contains(category.getImageName().toLowerCase())){
						List<PlaceOverlayItem> pois = dbHandler.loadOverlayPlaces(category, onlyOnePlaceID, assets);
						placeOverlays.addItemsBulk(pois);
					}
				}					
				runOnUiThread(new Runnable() {
					public void run() {
						placeOverlays.populateBulk();
						addOverlay();
						if(onlyOnePlaceID > 0)
							placeOverlays.showAnnotationAt(0, mapView);
					}
				});
				
			}
		}).start();		
		
		myLocationOverlay = new MyLocationOverlay(this, mapView);
		/*
		myLocationOverlay.runOnFirstFix(new Runnable() { public void run() {
		    mapController.animateTo(myLocationOverlay.getMyLocation());
		}});	
		 */	
	}
	
	
	
	private void clearOverlays(){
		removeOverlays();
		placeOverlays = null;
	}
	
	private void removeOverlays(){
		if(placeOverlays != null){
			placeOverlays.hideAnnotation();
			overlays.remove(placeOverlays);
		}
		overlays.remove(myLocationOverlay);
	}
	
	
	private void addOverlay(){
		removeOverlays();
		overlays.add(placeOverlays);
		overlays.add(myLocationOverlay);
		mapView.invalidate();
	}
	
	private void clearDirection(){
		if(gdm != null) gdm.clearMap();
		deleteDirectionButton.setVisibility(View.GONE);		
	}
	
	private void startDirection(){
		
		if(to == null) return;
		if(from == null && myLocationOverlay.getMyLocation() == null){			
			showUnknowLocationMessage();	  
			return;
		}		
		
		clearDirection();
		removeOverlays();
		
		gda = new GoogleDirectionAPI(GoogleDirectionAPI.PROTOCOL_HTTPS);
		gda.setDebugMode(false);
		gda.setOrigin(from != null ? from : myLocationOverlay.getMyLocation());
		gda.setDestination(to);
		gda.setAlternatives(false);
		gda.setMode(GoogleDirectionAPI.MODE_DRIVING);
		gda.setRegion("hu");
		gda.setUnits(GoogleDirectionAPI.UNIT_METRIC);
		gda.setLanguage(Locale.getDefault().getLanguage());
		gda.setOnDirectionListener(new GoogleDirectionAPI.DirectionListener() {
			public void onFail(String errorStatus) {
				Toast.makeText(MapsActivity.this, errorStatus, Toast.LENGTH_LONG).show();
			}
			@Override
			public void onSuccess(List<Route> arg0) {
				Toast.makeText(MapsActivity.this, "KÉSZ", Toast.LENGTH_LONG).show();				
				gdm.drawMap(gda);
				gdm.showAnnotationFirst();
				overlays.add(myLocationOverlay);
				deleteDirectionButton.setVisibility(View.VISIBLE);
			}
		});
		gda.start();
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		gestureDetector.onTouchEvent(ev);
		return super.dispatchTouchEvent(ev);
	}	
	
	
	private class MyGestureListener extends SimpleOnGestureListener{		
		public boolean onDoubleTap(MotionEvent e) {
			if(mapController != null) mapController.zoomIn();
			return super.onDoubleTap(e);
		}		
		/*
		public boolean onSingleTapConfirmed(MotionEvent e) {
			if(placeOverlays != null) placeOverlays.hideAnnotation();
			return super.onSingleTapConfirmed(e);
		}*/
	}
	
	private void showUnknowLocationMessage(){
		final BUGDialog bd = new BUGDialog(this);
		bd.setMessage(R.string.err_map_missing_from);
		bd.setPositiveButton(R.string.ok, new OnClickListener() {
			public void onClick(View v) {
				bd.dismiss();
			}
		});
		bd.setNegativeButton(R.string.settings, new OnClickListener() {
			public void onClick(View v) {
				startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
				bd.dismiss();
			}
		});
		bd.show();
	}
	
	public static void showOnMap(Context context, int placeID){
		Intent i = new Intent(context, MapsActivity.class);
			   i.putExtra(KEY_PLACE_ID, placeID);
		context.startActivity(i);
	}
	
	@Override
	protected boolean isRouteDisplayed() { return false; }

}
